#ifndef _TEST_RTTI_H_
#define _TEST_RTTI_H_
#include <gtest/gtest.h>
#include "core/core_utils.h"

using namespace z3d;

namespace tg{
	//=== TESTGAMEOBJECT ========================================
	class TestGameObject: public zelObject{
		RTTI_DECLARATION
	public:
		/*
		virtual void printMessage()
		{
			std::cout << "Hi from TestGameObject" << std::endl;
		}
		*/
		void tgo_greetingsFromTestGameObject()
		{
			std::cout << "Greetings from testGameObject!!!" << std::endl;
		}

	};
	RTTI_IMPLEMENTATION(tg, zelObject, TestGameObject);

	//==== DERIVEDGAMEOBJECT ===================================
	class DerivedGameObject: public TestGameObject{
			RTTI_DECLARATION
		public:
			/*
			void printMessage()
			{
				std::cout << "Hi from DerivedGameObject" << std::endl;
			}
			*/
			void dgo_greetingsFromDeriveGameObject()
			{
				std::cout << "Greetings from DerivedGameObject!!!" << std::endl;
			}

	};
	RTTI_IMPLEMENTATION(tg, TestGameObject, DerivedGameObject);

	//==== SUBDERIVEDGAMEOBJECT ================================
	class SubDerivedGameObject: public DerivedGameObject{
				RTTI_DECLARATION
			public:
				void printMessage()
				{
					std::cout << "Hi from DerivedGameObject" << std::endl;
				}
				void tgo_greetingsFromSubDerivedGameObject()
				{
					std::cout << "Greetings from SubDerivedGameObject!!!" << std::endl;
				}

	};
	RTTI_IMPLEMENTATION(tg, DerivedGameObject, SubDerivedGameObject);
};


class RTTI_TestFixture: public ::testing::Test
{
public:
	tg::TestGameObject m_testGameObject;
	tg::DerivedGameObject m_derivedGameObject;
	tg::SubDerivedGameObject m_subDerivedGameObject;
};

TEST_F(RTTI_TestFixture, class_name_is_correctly_assigned)
{
	std::string actual(m_testGameObject.GetRttiType().GetName());
	EXPECT_EQ(actual, std::string("tg.TestGameObject"));
}

TEST_F(RTTI_TestFixture, superclass_is_correctly_assigned)
{

	EXPECT_EQ(std::string(m_derivedGameObject.GetRttiType().GetName()), std::string("tg.DerivedGameObject"));

}
TEST_F(RTTI_TestFixture, type_is_correctly_identified)
{
	EXPECT_TRUE(m_derivedGameObject.IsDerived(m_testGameObject.GetRttiType()));
	EXPECT_TRUE(m_derivedGameObject.IsDerivedTypeOf(&m_testGameObject));
	EXPECT_FALSE(m_derivedGameObject.IsExactly(m_testGameObject.GetRttiType()));
	EXPECT_FALSE(m_derivedGameObject.IsExactlyTypeOf(&m_testGameObject));

	//with 2 derived depth
	EXPECT_TRUE(m_subDerivedGameObject.IsDerived(m_derivedGameObject.GetRttiType()));
	EXPECT_TRUE(m_subDerivedGameObject.IsDerived(m_testGameObject.GetRttiType()));

	EXPECT_TRUE(m_subDerivedGameObject.IsDerivedTypeOf(&m_derivedGameObject));
	EXPECT_TRUE(m_subDerivedGameObject.IsDerivedTypeOf(&m_testGameObject));

	EXPECT_FALSE(m_subDerivedGameObject.IsExactly(m_derivedGameObject.GetRttiType()));
	EXPECT_FALSE(m_subDerivedGameObject.IsExactly(m_testGameObject.GetRttiType()));

	EXPECT_TRUE(m_subDerivedGameObject.IsDerived(m_subDerivedGameObject.GetRttiType()));
}


#endif //_TEST_RTTI_H_
